package com.yulinlin.admin.core.dao;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.yulinlin.admin.core.domain.SuperEntity;
import com.yulinlin.jdbc.model.anno.JoinPrimary;
import com.yulinlin.jdbc.model.wrapper.ModelDeleteWrapper;
import com.yulinlin.jdbc.model.wrapper.ModelSelectWrapper;
import com.yulinlin.lang.util.GenericUtil;
import com.yulinlin.lang.util.ReflectionUtil;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public abstract class SuperDao <E extends SuperEntity<E>> {

    //雪花id
    private Snowflake snowflake  =     IdUtil.createSnowflake(0,0);

    protected long nextId()
    {
      return   snowflake.nextId();
    }

    private String getPrimaryKey(){
        List<Field> fs =  ReflectionUtil.getAllDeclaredFields(this.getEntityClass());
        for (Field f : fs) {
            JoinPrimary joinPrimary =   f.getAnnotation(JoinPrimary.class);
            if(joinPrimary != null){
              return f.getName();
            }
        }
        throw new RuntimeException("缺少主键字段");
    }

  public   List<E> findByIdIn(List<Long> ids){
      ModelSelectWrapper<E> selectWrapper =  this.newInstance().createSelectWrapper();
      selectWrapper.wrapper().where().in(getPrimaryKey(),ids);
      return selectWrapper.selectList();
    }

    public  E findById(String id){
        ModelSelectWrapper<E> selectWrapper =  this.newInstance().createSelectWrapper();
        selectWrapper.wrapper().where().eq(getPrimaryKey(),id);
        return  selectWrapper.selectOne();
    }

    public   int insertOne(E obj){
        return insertList(Arrays.asList(obj));
    }

    public   int insertList(List<E> coll){
        int total = 0;
        for (E obj: coll) {
            obj.setId(nextId());
            obj.setCrtTime(new Date());
            obj.setUptTime(new Date());
            total += obj.createInsertWrapper().execute();
        }

        return  total;
    }

    public int deleteById(String id){
        ModelDeleteWrapper<E> wrapper =  this.newInstance().createDeleteWrapper();
        return wrapper.wrapper().where().eq(this.getPrimaryKey(),id).end().end().execute();
    }


    public  int deleteByIdIn(List<Long> coll){
        ModelDeleteWrapper<E> wrapper =  this.newInstance().createDeleteWrapper();
        return wrapper.wrapper().where().in(this.getPrimaryKey(),coll).end().end().execute();

    }

    public  int updateOne(E obj){
        return updateList(Arrays.asList(obj));
    }

    public int updateList(List<E> list){

        int total = 0;
        for (E e : list) {
            total += e.createUpdateWrapper().execute();
        }
        return  total;
    }

    public List<E> all(){
      return this.newInstance().createSelectWrapper().selectList();
    }

    public Class getEntityClass(){
        return GenericUtil.getGeneric(this.getClass(),SuperDao.class,0);
    }

    public E newInstance(){
        return (E)ReflectionUtil.newInstance( getEntityClass());
    }


}
